package sceneGraph;

import javax.vecmath.*;

public class Camera extends SceneGraphNode {

	protected Point3f pos;
	private Point3f lookAt;
	private Vector3f upDirection;

	private Vector3f direction;

	private boolean isMapMode;

	private Player player;
	private AbstractPlanet planet;

	public Camera() {
		pos = new Point3f(0, 0, 100);
		lookAt = new Point3f(0, 0, 0);
		upDirection = new Vector3f(0, 1, 0);

		direction = new Vector3f();
		direction.sub(lookAt, pos);
		direction.normalize();

		isMapMode = false;

	}

	public void setPlayer(Player player, AbstractPlanet curPlanet) {
		this.player = player;
		this.planet = curPlanet;
	}

	public Player getPlayer() {
		return player;
	}

	public AbstractPlanet getPlanet() {
		return planet;
	}

	public boolean isMapMode() {
		return isMapMode;
	}

	public void toggleMapMode() {
		isMapMode = !isMapMode;
		if (isMapMode) {
			pos = new Point3f(player.getPosition());
			pos.scale(8);
		}
	}

	public Point3f getPosition() {
		return pos;
	}

	public Point3f getLookAt() {
		return lookAt;
	}

	public Vector3f getDirection() {
		return direction;
	}

	public Vector3f getUpDirection() {
		return upDirection;
	}

	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}

	public void setUpDirection(Vector3f newUpDirection) {
		upDirection = new Vector3f(newUpDirection);
		upDirection.normalize();
	}

	public void setPoisition(Point3f newPos) { // Updates the up vector accordingly
		pos = new Point3f(newPos);

		// Calculate the new direction
		direction = new Vector3f();
		direction.sub(lookAt, pos);
		direction.normalize();

		// Calculate the new up direction
		upDirection.cross(direction, getLeftDirection());
		upDirection.normalize();
	}

	public void setLookAt(Point3f newLookAt) {
		lookAt = new Point3f(newLookAt);
		direction = new Vector3f();
		direction.sub(lookAt, pos);
		direction.normalize();
	}

	public Vector3f getLeftDirection() {
		Vector3f leftDirection = new Vector3f();
		leftDirection.cross(upDirection, direction);
		leftDirection.normalize();

		return leftDirection;
	}

	public Point3f getAbsPosition() {
		Point3f absPos = new Point3f();
		absPos.add(pos, planet.getAbsPosition());

		return absPos;
	}

	public Point3f getAbsLookAt() {
		Point3f absPos = new Point3f();
		absPos.add(lookAt, planet.getAbsPosition());

		return absPos;
	}

}
